#pragma once

#include "../httplib.h"
#include "Contacts.pb.h"
#include "ContactException.h"
#include <fstream>
#include <random>
#include <sstream>
#include <unordered_map>
class Serve
{
    static unsigned int random_char()
    {
        // ⽤于随机数引擎获得随机种⼦
        std::random_device rd;
        // mt19937是c++11新特性，它是⼀种随机数算法，⽤法与rand()函数类似，但是mt19937具有速度快，周期⻓的特点
        // 作⽤是⽣成伪随机数
        std::mt19937 gen(rd());
        // 随机⽣成⼀个整数i 范围[0, 255]
        std::uniform_int_distribution<> dis(0, 255);
        return dis(gen);
    }

    // ⽣成 UUID （通⽤唯⼀标识符）
    static std::string generate_hex(const unsigned int len)
    {
        std::stringstream ss;
        // ⽣成 len 个16进制随机数，将其拼接⽽成
        for (auto i = 0; i < len; i++)
        {
            const auto rc = random_char();
            std::stringstream hexstream;
            hexstream << std::hex << rc;
            auto hex = hexstream.str();
            ss << (hex.length() < 2 ? '0' + hex : hex);
        }
        return ss.str();
    }

private:
    httplib::Server _serve;
    ContactsServe::contactsserve _contacts;
    std::unordered_map<std::string, AddPeople::AddPeopleRequest> _uid_people;

private:
    void OnAddpeople(const httplib::Request &requ, httplib::Response &res)
    {
        try
        {
            // 生成唯一ID
            std::string uid = generate_hex(8);
            // 对请求进行反序列化
            AddPeople::AddPeopleRequest people;
            bool parse = people.ParseFromString(requ.body);
            if (!parse)
            {
                throw ContactException("反序列化请求body失败");
            }
            // 反序列化成功后加入我们的通讯录
            AddPeople::AddPeopleRequest *onepeople = _contacts.add_people();
            onepeople->CopyFrom(people);
            // 更新内存映射
            _uid_people[uid] = people;
            // 保存到文件
            std::ofstream out("./contacts.bin", std::ios::binary);
            if (!_contacts.SerializeToOstream(&out))
            {
                throw ContactException("保存通讯录到文件失败");
            }
            out.close();

            // 返回成功响应
            AddPeople::AddPeopleResponse response;
            response.set_success(true);
            response.set_uid(uid);

            std::string response_str;
            response.SerializeToString(&response_str);
            res.set_content(response_str, "application/x-protobuf");
            res.status = 200;
        }
        catch (const ContactException &e)
        { // httblib 自动发送 此时没有设置body 客户端进行body的反序列化会失败
            res.status = 400;
            res.set_content(e.what(), "text/plain");
        }
        catch (const std::exception &e)
        {
            res.status = 500;
            std::cerr << e.what() << '\n';
        }
    }

public:
    Serve()
    {
        // 把磁盘文件加载我们的内存_contacts
        std::ifstream in("./contacts.bin", std::ios::binary);
        if (in.is_open() == false)
        {
            std::cout << "通讯录文件不存在，将创建新文件" << std::endl;
        }
        bool parse = _contacts.ParseFromIstream(&in);
        if (!parse)
        {
            throw ContactException("加载本地磁盘通讯录失败");
        }
        in.close();
        std::cout << "成功加载 " << _contacts.people_size() << " 个联系人" << std::endl;
        // 进行我们的_uid_people构建
        // 进行我们的_uid_people构建
        for (int i = 0; i < _contacts.people_size(); i++)
        {
            const AddPeople::AddPeopleRequest &person = _contacts.people(i);
            std::string uid = generate_hex(8); // 为每个联系人生成唯一ID
            _uid_people[uid] = person;
        }
    }

public:
    void HandlerAddOnePeople()
    {
        _serve.Post("/contacts/add", [this](const httplib::Request &requ, httplib::Response &res)
                    { this->OnAddpeople(requ, res); });
    }
    void Start()
    {
        _serve.listen("115.190.43.87", 8086);
    }
};